package gb

import (
	"bytes"
	"encoding/xml"
	"io"
	"net/http"

	"gitee.com/tonyjia/gb28181/pkg/event"
	"gitee.com/tonyjia/gb28181/pkg/model"
	model2 "gitee.com/tonyjia/gb28181/pkg/model"
	parser2 "gitee.com/tonyjia/gb28181/pkg/parser"
	"github.com/ghettovoice/gosip/sip"
	log "github.com/sirupsen/logrus"
	"golang.org/x/text/encoding/simplifiedchinese"
)

/**
 * @Description
 * @Author lulili
 * @Date 2024/10/17 16:23
 */

func NotifyHandler(req sip.Request, tx sip.ServerTransaction) {
	log.Info("Info消息体：\n%s", req)
	if l, ok := req.ContentLength(); !ok || l.Equals(0) {
		log.Debug("该Info消息的消息体长度为0，返回OK")
		_ = tx.Respond(sip.NewResponseFromRequest("", req, http.StatusOK, http.StatusText(http.StatusOK), ""))
	}
	body := req.Body()
	cmdType, err := parser2.GetCmdTypeFromXML(body)
	log.Debug("解析出的命令：", cmdType)
	if err != nil {
		return
	}
	handler, ok := messageHandler[cmdType]
	if !ok {
		log.Warn("不支持的Info方法实现")
		return
	}
	handler(req, tx)
}

func catalogNotifyHandler(req sip.Request, tx sip.ServerTransaction) {
	defer func() {
		_ = responseAck(tx, req)
	}()

	catalog := model2.DeviceCatalogResponse{}

	err := xml.Unmarshal([]byte(req.Body()), &catalog)

	if err != nil {
		// maybe charset is GBK, so take request body convert utf8
		b, err := gbkToUtf8([]byte(req.Body()))

		if err != nil {
			log.Error(err)
			return
		}
		err = xml.Unmarshal(b, &catalog)
		if err != nil {
			log.Error(err)
			return
		}
	}

	eventBus := event.GetEventBus()
	eventBus.Publish(event.Catalog, catalog)
}

func keepaliveNotifyHandler(req sip.Request, tx sip.ServerTransaction) {
	keepalive := &model.Keepalive{}
	reader := bytes.NewReader([]byte(req.Body()))
	decoder := xml.NewDecoder(reader)
	decoder.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
		switch charset {
		case "gb2312":
			return simplifiedchinese.GB18030.NewDecoder().Reader(input), nil
		default:
			return input, nil
		}
	}
	if err := decoder.Decode(&keepalive); err != nil {
		log.Error("解析响应包出错", err)
		return
	}
	device, ok := parser2.DeviceFromRequest(req)
	if !ok {
		return
	}
	//获取到设备信息回调
	log.Infof("设备信息为：%+v", device)
	_ = tx.Respond(sip.NewResponseFromRequest("", req, http.StatusOK, http.StatusText(http.StatusOK), ""))

	eventBus := event.GetEventBus()
	eventBus.Publish(event.Keepalive, keepalive)
}
